/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFTstop
  \brief a plastic scintillator placed at F1 of RIBLL2, single-ended
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-10-30
  \date 2022-04-26 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-10-30   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <cstring>
#include <TClonesArray.h>
#include <TGraph.h>
#include "FairRootManager.h"
#include "ETFTstop.h"
#include "ETFDetectorManager.h"
#include "ETFHPTDCChannel.h"
#include "ETFPlaHit.h"
#include "ETFMath.h"
#include "ETFMsg.h"
#include "ETFParaManager.h"
#include "ETFYaml.h"

ClassImp(ETFTstop);

static const double DEGREE = ETFMath::DEGREE();

ETFTstop::ETFTstop(const char *name) : ETFTimer(name){
  ETFParaManager *pm = ETFParaManager::Instance();
  const YAML::Node &chIdConfig = (*pm->GetChIdPara())[name];
  const int chId0 = chIdConfig.as<int>();
  if(chId0 >= 0 && !strcmp(name, "tstop")){ // PXI channels
    SetChIdMap(chId0,   fDetId);
    SetChIdMap(chId0+1, fDetId + (1<<8));
    SetChIdMap(chId0+2, fDetId + (2<<8));
    SetChIdMap(chId0+3, fDetId + (3<<8));
    // pass user trig bound parameters //
    const YAML::Node &trigBConfig = (*pm->GetMisPara())["tstopTrigB"];
    if(trigBConfig){
      fTrigLB = trigBConfig[0].as<double>();
      fTrigHB = trigBConfig[1].as<double>();
    } // end if
  } // end if
  // VME hits, would be removed in future versions, just for backward compatibility
  if(chId0 > 8000 && (!strcmp(name, "tstop1") || !strcmp(name, "tstop0"))){
    SetChIdMap(chId0,   fDetId, true);
    SetChIdMap(chId0+1, fDetId + (2<<8), true);
    SetChIdMap(chId0+2, -2, true);
    SetChIdMap(chId0+3, -2, true);
  } // end if

  fHits = new TClonesArray("ETFPlaHit");
  fHits->SetName(name);
} // end ctor

// add the data channel to the detector
void ETFTstop::Assign(const ETFHPTDCChannel *ch){
  int uid = ETFDetectorManager::Instance()->GetUID(ch->GetChannelId());
  if(fDetId != (uid & 0xFF)) ETFMsg::Error("ETFTstop", "Assign: not from this detector.");
  int udvh = uid>>8 & 0x3;
  AddHit(ch, udvh);
} // end member function Assign

void ETFTstop::AddHit(const ETFHPTDCChannel *ch, int udvh){
  ETFPlaHit *hit = nullptr;
  for(auto p : *fHits){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(p);
    if(0 == h->GetStripId()){ // old strip
      hit = h; continue;
    } // end if
  } // end for
  if(!hit){ // the strip of this hit has not been registered
    hit = dynamic_cast<ETFPlaHit *>(fHits->ConstructedAt(fHits->GetEntries()));
    hit->Initialize();
    hit->SetStripId(0);
    hit->SetLength(500.);
    double pos[3]{};
    hit->SetPosition(pos);
    hit->SetDelay(fDelay);
    TransformToLabRef(hit);
  } // end if(hit is nullptr)
  hit->SetDataChannel(ch, udvh);
} // end member function AddHit

double ETFTstop::GetTime() const{
  if(!fHits->GetEntries()) ETFMsg::Error("ETFStart", "GetTime: No hits in Tstop");
  return dynamic_cast<ETFPlaHit *>(fHits->At(0))->GetTime();
} // end member function GetTime

// return the fired status of Tstop
int ETFTstop::GetFiredStatus() const{
  if(!fHits->GetEntries()) return -1;
  return dynamic_cast<ETFPlaHit *>((*fHits)[0])->GetFiredStatus();
} // end member function GetFiredStatus

// add strip to fGDumb
void ETFTstop::ConstructGraph(){
  if(fGDumb->GetN()) return; // has called

  fGDumb->SetMarkerStyle(28);
  fGDumb->SetMarkerColor(30); // gray
  double p[3]{};
  TransformToLabRef(p);
  fGDumb->SetPoint(0, p[2], p[0]);
} // end member function ConstructGraph

void ETFTstop::DrawHits(){
  for(const auto &p : *fHits) if(p){
    ETFPlaHit *h = dynamic_cast<ETFPlaHit *>(p);
    h->GetGHit()->SetMarkerStyle(21);
    if(h->GetFiredStatus() == 4) h->Draw();
  } // end for and if
} // end member function DrawHits
